package com.bluexmicro.module_componment.scan

import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.SeekBar
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bluexmicro.module_componment.SpaceItemDecoration
import com.bluexmicro.module_componment.databinding.FragmentInnerScanDevicesBinding
import com.bluexmicro.module_componment.singleTap
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean

/**
 * 生命周期跟随Activity
 */
class ScanDeviceFragment : Fragment() {

    private var mBinding: FragmentInnerScanDevicesBinding? = null

    private val viewModel by activityViewModels<ScanViewModel> {
        ScanViewModelFactory(requireActivity().application)
    }
    private val deviceAdapter = ScanAdapter { index ->
        onSelectedDevice(index)
    }

    private var settingPageLauncher: ActivityResultLauncher<Intent>? = null
    private var scanPermissionLauncher: ActivityResultLauncher<String>? = null
    private var connectPermissionLauncher: ActivityResultLauncher<String>? = null
    private var locationPermissionLauncher: ActivityResultLauncher<String>? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val binding = FragmentInnerScanDevicesBinding.inflate(inflater, container, false)
        mBinding = binding
        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        mBinding = null
    }

    private fun onSelectedDevice(index: Int) {
        if (index in deviceAdapter.currentList.indices) {
            viewModel.pickSomeOne(deviceAdapter.currentList[index])
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        settingPageLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
                viewModel.checkConditions()
            }
        scanPermissionLauncher =
            registerForActivityResult(ActivityResultContracts.RequestPermission()) {
                if (!it && isNeverAck(Manifest.permission.BLUETOOTH_SCAN)) {
                    manualGrant()
                } else {
                    viewModel.checkConditions()
                }
            }
        connectPermissionLauncher =
            registerForActivityResult(ActivityResultContracts.RequestPermission()) {
                if (!it && isNeverAck(Manifest.permission.BLUETOOTH_CONNECT)) {
                    manualGrant()
                } else {
                    viewModel.checkConditions()
                }
            }
        locationPermissionLauncher =
            registerForActivityResult(ActivityResultContracts.RequestPermission()) {
                if (!it && isNeverAck(Manifest.permission.ACCESS_FINE_LOCATION)) {
                    manualGrant()
                } else {
                    viewModel.checkConditions()
                }
            }

        mBinding?.apply {
            setupConditions()
            devicesView.setupDevicesView()
            setupFilters()

            updateBtn.setOnClickListener {
                viewModel.filterAndSortList()
            }

        }

    }

    override fun onResume() {
        super.onResume()
        viewModel.checkConditions()
    }

    ///////////////////////////////////////////////////////////////////////////
    // device list
    ///////////////////////////////////////////////////////////////////////////
    private fun RecyclerView.setupDevicesView() {
        layoutManager = LinearLayoutManager(context)
//        val decoration = SpaceItemDecoration(bottomDp = 8)
//        addItemDecoration(decoration)
        addItemDecoration(DividerItemDecoration(context, RecyclerView.VERTICAL))
        adapter = deviceAdapter


        lifecycleScope.launch {
            viewModel.displayDevices.collect {
                deviceAdapter.submitList(it)

                mBinding?.scanningView?.visibility = if (it.isEmpty()) View.VISIBLE else View.GONE
            }
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Filter
    ///////////////////////////////////////////////////////////////////////////

    @SuppressLint("SetTextI18n")
    private fun FragmentInnerScanDevicesBinding.setupFilters() {
        lifecycleScope.launch {
            viewModel.filters.collect {
                //display layout
                rssiFilterTx.text = "${it.rssiThreshold}mdb"
                connectableFilterTx.visibility = if (it.connectable) View.VISIBLE else View.GONE
                flagFilterTx.visibility = if (!it.flag.isNullOrEmpty()) {
                    flagFilterTx.text = it.flag
                    View.VISIBLE
                } else View.GONE
                //config page

                rssiSeekBar.progress = it.rssiThreshold + 127
                currentRssiThresholdTx.text = "Current: ${it.rssiThreshold}"

                flagEt.setText(it.flag ?: "")
                connectableCheckBox.isChecked = it.connectable

                filtersConfiguringLayout.visibility =
                    if (it.configuring) View.VISIBLE else View.GONE
            }
        }

        rssiSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                currentRssiThresholdTx.text = "Current: ${progress - 127}"
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
            }

        })

        filterLayout.setOnClickListener {
            viewModel.setConfiguring(true)
        }

        saveFiltersBtn.setOnClickListener {
            val rssiThreshold = rssiSeekBar.progress - 127
            val flag = flagEt.text.toString()
            val connectable = connectableCheckBox.isChecked
            viewModel.saveFilters(rssiThreshold, connectable, flag)
        }

        cancelFiltersBtn.setOnClickListener {
            viewModel.setConfiguring(false)
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // condition
    ///////////////////////////////////////////////////////////////////////////

    @SuppressLint("SetTextI18n")
    private fun FragmentInnerScanDevicesBinding.setupConditions() {
        lifecycleScope.launch {
            viewModel.conditions.collect {
                conditionsLayout.visibility = if (it.isScanReady()) View.GONE else View.VISIBLE

                bluetoothItem.nameTx.text = "Bluetooth"
                bluetoothItem.descTx.text = "Use 'Bluetooth' feature to discover BLE Device"
                if (it.bluetoothEnable) {
                    bluetoothItem.root.isEnabled = false
                    bluetoothItem.actionTx.isEnabled = false
                    bluetoothItem.actionTx.text = "Ready"
                } else {
                    bluetoothItem.root.isEnabled = true
                    bluetoothItem.actionTx.isEnabled = true
                    bluetoothItem.actionTx.text = "enable"
                }

                locationItem.nameTx.text = "Location"
                locationItem.descTx.text =
                    "Use the 'Location' feature to measure the signal strength of BLE device"
                if (it.locationEnable) {
                    locationItem.root.isEnabled = false
                    locationItem.actionTx.isEnabled = false
                    locationItem.actionTx.text = "Ready"
                } else {
                    locationItem.root.isEnabled = true
                    locationItem.actionTx.isEnabled = true
                    locationItem.actionTx.text = "enable"
                }

                scanPermissionItem.nameTx.text = "Bluetooth Scan Permission"
                scanPermissionItem.descTx.text =
                    "To use the 'Bluetooth Scan' feature must Grant app 'Bluetooth Scan' permission"
                if (it.bluetoothScanPermission) {
                    scanPermissionItem.root.isEnabled = false
                    scanPermissionItem.actionTx.isEnabled = false
                    scanPermissionItem.actionTx.text = "Ready"
                } else {
                    scanPermissionItem.root.isEnabled = true
                    scanPermissionItem.actionTx.isEnabled = true
                    scanPermissionItem.actionTx.text = "Grant"
                }

                connectPermissionItem.nameTx.text = "Bluetooth Connect Permission"
                connectPermissionItem.descTx.text =
                    "To use the 'Bluetooth Connect' feature must Grant app 'Bluetooth Connect' permission"
                if (it.bluetoothConnectPermission) {
                    connectPermissionItem.root.isEnabled = false
                    connectPermissionItem.actionTx.isEnabled = false
                    connectPermissionItem.actionTx.text = "Ready"
                } else {
                    connectPermissionItem.root.isEnabled = true
                    connectPermissionItem.actionTx.isEnabled = true
                    connectPermissionItem.actionTx.text = "Grant"
                }

                locationPermissionItem.nameTx.text = "Location Permission"
                locationPermissionItem.descTx.text =
                    "To use the 'Location' feature must Grant app 'Location' permission"
                if (it.locationPermission) {
                    locationPermissionItem.root.isEnabled = false
                    locationPermissionItem.actionTx.isEnabled = false
                    locationPermissionItem.actionTx.text = "Granted"
                } else {
                    locationPermissionItem.root.isEnabled = true
                    locationPermissionItem.actionTx.isEnabled = true
                    locationPermissionItem.actionTx.text = "Grant"
                }
            }
        }

        bluetoothItem.actionTx.singleTap {
            viewModel.enableBluetooth()
        }

        locationItem.actionTx.singleTap {
            val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
            settingPageLauncher?.launch(intent)
        }

        scanPermissionItem.actionTx.singleTap {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                beforeCheckNeverAck(Manifest.permission.BLUETOOTH_SCAN)
                scanPermissionLauncher?.launch(Manifest.permission.BLUETOOTH_SCAN)
            }
        }

        connectPermissionItem.actionTx.singleTap {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                beforeCheckNeverAck(Manifest.permission.BLUETOOTH_CONNECT)
                connectPermissionLauncher?.launch(Manifest.permission.BLUETOOTH_CONNECT)
            }
        }

        locationPermissionItem.actionTx.singleTap {
            beforeCheckNeverAck(Manifest.permission.ACCESS_FINE_LOCATION)
            locationPermissionLauncher?.launch(Manifest.permission.ACCESS_FINE_LOCATION)
        }
    }

    private val pendingTask = AtomicBoolean(false)

    /**
     * 如果request前是true，response是false，不用处理
     * 如果request前是false，response是false，执行跳转
     */
    private fun beforeCheckNeverAck(permission: String) {
        pendingTask.set(!shouldShowRequestPermissionRationale(permission))
    }

    /**
     * 要在ActivityResult中执行
     */
    private fun isNeverAck(permission: String): Boolean {
        val flag = !shouldShowRequestPermissionRationale(permission)
        return pendingTask.compareAndSet(true, false) && flag
    }

    /**
     * 跳转到设置页面
     */
    private fun manualGrant() {
        val intent = Intent()
        intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
        intent.data = Uri.parse("package:${requireContext().packageName}")
        settingPageLauncher?.launch(intent)
//        startActivity(intent)
    }
}